﻿// Decompiled with JetBrains decompiler
// Type: UnityEngine.Bounds
// Assembly: UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: E6AE6B5A-2752-4B07-9528-C8B77C62CE79
// Assembly location: C:\Users\windys\Unity\2021.3.39f1c1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.dll
// XML documentation location: C:\Users\windys\Unity\2021.3.39f1c1\Editor\Data\Managed\UnityEngine\UnityEngine.CoreModule.xml

using System;
using System.Globalization;
using System.Runtime.CompilerServices;
using UnityEngine.Bindings;
using UnityEngine.Scripting;

#nullable disable
namespace UnityEngine
{
  /// <summary>
  ///   <para>Represents an axis aligned bounding box.</para>
  /// </summary>
  [NativeHeader("Runtime/Geometry/Intersection.h")]
  [NativeClass("AABB")]
  [NativeHeader("Runtime/Math/MathScripting.h")]
  [NativeHeader("Runtime/Geometry/AABB.h")]
  [RequiredByNativeCode(Optional = true, GenerateProxy = true)]
  [NativeHeader("Runtime/Geometry/Ray.h")]
  [NativeType(Header = "Runtime/Geometry/AABB.h")]
  /// <summary>
  ///   <para>Creates a new Bounds.</para>
  /// </summary>
  /// <param name="center">The location of the origin of the Bounds.</param>
  /// <param name="size">The dimensions of the Bounds.</param>
  public struct Bounds(Vector3 center, Vector3 size) : IEquatable<Bounds>, IFormattable
  {
    private Vector3 m_Center = center;
    [NativeName("m_Extent")]
    private Vector3 m_Extents = size * 0.5f;

    public override int GetHashCode()
    {
      Vector3 vector3 = this.center;
      int hashCode = vector3.GetHashCode();
      vector3 = this.extents;
      int num = vector3.GetHashCode() << 2;
      return hashCode ^ num;
    }

    public override bool Equals(object other) => other is Bounds other1 && this.Equals(other1);

    public bool Equals(Bounds other)
    {
      return this.center.Equals(other.center) && this.extents.Equals(other.extents);
    }

    /// <summary>
    ///   <para>The center of the bounding box.</para>
    /// </summary>
    public Vector3 center
    {
      get => this.m_Center;
      set => this.m_Center = value;
    }

    /// <summary>
    ///   <para>The total size of the box. This is always twice as large as the extents.</para>
    /// </summary>
    public Vector3 size
    {
      get => this.m_Extents * 2f;
      set => this.m_Extents = value * 0.5f;
    }

    /// <summary>
    ///   <para>The extents of the Bounding Box. This is always half of the size of the Bounds.</para>
    /// </summary>
    public Vector3 extents
    {
      get => this.m_Extents;
      set => this.m_Extents = value;
    }

    /// <summary>
    ///   <para>The minimal point of the box. This is always equal to center-extents.</para>
    /// </summary>
    public Vector3 min
    {
      get => this.center - this.extents;
      set => this.SetMinMax(value, this.max);
    }

    /// <summary>
    ///   <para>The maximal point of the box. This is always equal to center+extents.</para>
    /// </summary>
    public Vector3 max
    {
      get => this.center + this.extents;
      set => this.SetMinMax(this.min, value);
    }

    public static bool operator ==(Bounds lhs, Bounds rhs)
    {
      return lhs.center == rhs.center && lhs.extents == rhs.extents;
    }

    public static bool operator !=(Bounds lhs, Bounds rhs) => !(lhs == rhs);

    /// <summary>
    ///   <para>Sets the bounds to the min and max value of the box.</para>
    /// </summary>
    /// <param name="min"></param>
    /// <param name="max"></param>
    public void SetMinMax(Vector3 min, Vector3 max)
    {
      this.extents = (max - min) * 0.5f;
      this.center = min + this.extents;
    }

    /// <summary>
    ///   <para>Grows the Bounds to include the point.</para>
    /// </summary>
    /// <param name="point"></param>
    public void Encapsulate(Vector3 point)
    {
      this.SetMinMax(Vector3.Min(this.min, point), Vector3.Max(this.max, point));
    }

    /// <summary>
    ///   <para>Grow the bounds to encapsulate the bounds.</para>
    /// </summary>
    /// <param name="bounds"></param>
    public void Encapsulate(Bounds bounds)
    {
      this.Encapsulate(bounds.center - bounds.extents);
      this.Encapsulate(bounds.center + bounds.extents);
    }

    /// <summary>
    ///   <para>Expand the bounds by increasing its size by amount along each side.</para>
    /// </summary>
    /// <param name="amount"></param>
    public void Expand(float amount)
    {
      amount *= 0.5f;
      this.extents += new Vector3(amount, amount, amount);
    }

    /// <summary>
    ///   <para>Expand the bounds by increasing its size by amount along each side.</para>
    /// </summary>
    /// <param name="amount"></param>
    public void Expand(Vector3 amount) => this.extents += amount * 0.5f;

    /// <summary>
    ///   <para>Does another bounding box intersect with this bounding box?</para>
    /// </summary>
    /// <param name="bounds"></param>
    public bool Intersects(Bounds bounds)
    {
      return (double) this.min.x <= (double) bounds.max.x && (double) this.max.x >= (double) bounds.min.x && (double) this.min.y <= (double) bounds.max.y && (double) this.max.y >= (double) bounds.min.y && (double) this.min.z <= (double) bounds.max.z && (double) this.max.z >= (double) bounds.min.z;
    }

    /// <summary>
    ///   <para>Does ray intersect this bounding box?</para>
    /// </summary>
    /// <param name="ray"></param>
    public bool IntersectRay(Ray ray) => Bounds.IntersectRayAABB(ray, this, out float _);

    public bool IntersectRay(Ray ray, out float distance)
    {
      return Bounds.IntersectRayAABB(ray, this, out distance);
    }

    /// <summary>
    ///   <para>Returns a formatted string for the bounds.</para>
    /// </summary>
    /// <param name="format">A numeric format string.</param>
    /// <param name="formatProvider">An object that specifies culture-specific formatting.</param>
    public override string ToString() => this.ToString((string) null, (IFormatProvider) null);

    /// <summary>
    ///   <para>Returns a formatted string for the bounds.</para>
    /// </summary>
    /// <param name="format">A numeric format string.</param>
    /// <param name="formatProvider">An object that specifies culture-specific formatting.</param>
    public string ToString(string format) => this.ToString(format, (IFormatProvider) null);

    /// <summary>
    ///   <para>Returns a formatted string for the bounds.</para>
    /// </summary>
    /// <param name="format">A numeric format string.</param>
    /// <param name="formatProvider">An object that specifies culture-specific formatting.</param>
    public string ToString(string format, IFormatProvider formatProvider)
    {
      if (string.IsNullOrEmpty(format))
        format = "F2";
      if (formatProvider == null)
        formatProvider = (IFormatProvider) CultureInfo.InvariantCulture.NumberFormat;
      return UnityString.Format("Center: {0}, Extents: {1}", (object) this.m_Center.ToString(format, formatProvider), (object) this.m_Extents.ToString(format, formatProvider));
    }

    /// <summary>
    ///   <para>Is point contained in the bounding box?</para>
    /// </summary>
    /// <param name="point"></param>
    [NativeMethod("IsInside", IsThreadSafe = true)]
    public bool Contains(Vector3 point) => Bounds.Contains_Injected(ref this, ref point);

    /// <summary>
    ///   <para>The smallest squared distance between the point and this bounding box.</para>
    /// </summary>
    /// <param name="point"></param>
    [FreeFunction("BoundsScripting::SqrDistance", HasExplicitThis = true, IsThreadSafe = true)]
    public float SqrDistance(Vector3 point) => Bounds.SqrDistance_Injected(ref this, ref point);

    [FreeFunction("IntersectRayAABB", IsThreadSafe = true)]
    private static bool IntersectRayAABB(Ray ray, Bounds bounds, out float dist)
    {
      return Bounds.IntersectRayAABB_Injected(ref ray, ref bounds, out dist);
    }

    /// <summary>
    ///   <para>The closest point on the bounding box.</para>
    /// </summary>
    /// <param name="point">Arbitrary point.</param>
    /// <returns>
    ///   <para>The point on the bounding box or inside the bounding box.</para>
    /// </returns>
    [FreeFunction("BoundsScripting::ClosestPoint", HasExplicitThis = true, IsThreadSafe = true)]
    public Vector3 ClosestPoint(Vector3 point)
    {
      Vector3 ret;
      Bounds.ClosestPoint_Injected(ref this, ref point, out ret);
      return ret;
    }

    [MethodImpl(MethodImplOptions.InternalCall)]
    private static extern bool Contains_Injected(ref Bounds _unity_self, ref Vector3 point);

    [MethodImpl(MethodImplOptions.InternalCall)]
    private static extern float SqrDistance_Injected(ref Bounds _unity_self, ref Vector3 point);

    [MethodImpl(MethodImplOptions.InternalCall)]
    private static extern bool IntersectRayAABB_Injected(
      ref Ray ray,
      ref Bounds bounds,
      out float dist);

    [MethodImpl(MethodImplOptions.InternalCall)]
    private static extern void ClosestPoint_Injected(
      ref Bounds _unity_self,
      ref Vector3 point,
      out Vector3 ret);
  }
}
